package com.fsxgt.datagrid.console.config;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import com.alibaba.fastjson2.JSON;
import com.fsxgt.datagrid.core.utils.ReturnT;
import com.fsxgt.datagrid.sys.service.impl.SysUserService;
import com.fsxgt.datagrid.sys.utils.MD5Util;

/**
 * 
 * prePostEnabled :决定Spring Security的前注解是否可用 [@PreAuthorize,@PostAuthorize,..]
 * 
 * secureEnabled : 决定是否Spring Security的保障注解 [@Secured] 是否可用
 * 
 * jsr250Enabled ：决定 JSR-250 annotations 注解[@RolesAllowed..] 是否可用.
 * 
 */

@Configurable

@EnableWebSecurity

//开启 Spring Security 方法级安全注解 @EnableGlobalMethodSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


	@Autowired
	private SysUserService sysUserService;
	



	

	@Override
	public void configure(WebSecurity webSecurity) {

		// 不拦截静态资源,所有用户均可访问的资源

		webSecurity.ignoring().antMatchers(
				"/html/**","/"
		);

	}

	/**
	 * 
	 * http请求设置
	 * 
	 */

	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.csrf().disable();
		http.authorizeRequests()
		    
		    .antMatchers("/executor/callback","/server/register").anonymous()
	        .antMatchers("/sysUser/findSysUserPage").access("@permissionHandler.hasPermission(request, authentication)")
	        .anyRequest().authenticated()
	        
		    .and().formLogin().permitAll().usernameParameter("username") // 登录用户名参数
				.passwordParameter("password") // 登录密码参数
				.successHandler(new AuthenticationSuccessHandler() {
					@Override
					public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
							Authentication authentication) throws IOException, ServletException {
						response.setContentType("application/json;charset=utf-8");
						response.getWriter().write(JSON.toJSONString(new ReturnT()));

					}
				})
				// 登录失败处理
				.failureHandler(new AuthenticationFailureHandler() {
					@Override
					public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
							AuthenticationException exception) throws IOException, ServletException {
						
						String result= "登录失败";
						
				        if (exception instanceof AccountExpiredException) {
				            //账号过期
				            result = "账号过期";
				        } else if (exception instanceof BadCredentialsException) {
				            //密码错误
				            result = "密码错误";
				        } else if (exception instanceof CredentialsExpiredException) {
				            //密码过期
				            result = "密码过期";
				        } else if (exception instanceof DisabledException) {
				            //账号不可用
				            result = "账号不可用";
				        } else if (exception instanceof LockedException) {
				            //账号锁定
				            result = "账号锁定";
				        } else if (exception instanceof InternalAuthenticationServiceException) {
				            //用户不存在
				            result = "用户不存在";
				        }
				        
						response.setContentType("application/json;charset=utf-8");
						response.getWriter().write(JSON.toJSONString(new ReturnT("202", result)));
					}
				})
			.and().logout().permitAll().logoutSuccessHandler(new LogoutSuccessHandler() {
			    @Override
			    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
			     
			    	httpServletResponse.getWriter().write(JSON.toJSONString(new ReturnT()));
			        
			    }}).deleteCookies("JSESSIONID")//登出之后删除cookie
			
			.and().exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
				@Override
				public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
						AccessDeniedException accessDeniedException) throws IOException, ServletException {
					httpServletResponse.setContentType("application/json;charset=utf-8");
			        httpServletResponse.getWriter().write(JSON.toJSONString(new ReturnT("202","没有权限")));
				}
				
			}) // 权限拒绝实现
			.authenticationEntryPoint(new AuthenticationEntryPoint() {
				@Override
				public void commence(HttpServletRequest request, HttpServletResponse response,
						AuthenticationException authException) throws IOException, ServletException {
					response.setContentType("application/json;charset=utf-8");
					response.getWriter().write(JSON.toJSONString(new ReturnT("800","未登录")));
				}
			})
        ;
		


	}

	/**
	 * 自定义获取用户信息接口
	 */
	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {

		auth.userDetailsService(sysUserService).passwordEncoder(new PasswordEncoder() {
			@Override
			public String encode(CharSequence rawPassword) {
				return MD5Util.encode((String) rawPassword);
			}

			@Override
			public boolean matches(CharSequence rawPassword, String encodedPassword) {
				return encodedPassword.equals(MD5Util.encode((String) rawPassword));
			}
		});

	}


}